﻿using System;
using System.Collections.Generic;
using System.Text;

namespace ttlang
{
    internal class CompilerElement
    {

        internal static void Parse(compiler.CompilerContext context, string name, src.AstNode node)
        {
            if (context.state == compiler.CompileState.FAIL)
                throw new Exception("has error,can't continue.");
            switch (node.type)
            {
                case "expr"://這個模式表達式沒有機會自己填充上下文，除非我提前塞值給他
                case "expr_postfix":
                case "expr_unary":
                case "expr_cast":
                case "expr_mul":
                case "expr_add":
                case "expr_shift":
                case "expr_relation":
                case "expr_equal":
                case "expr_and":
                case "expr_xor":
                case "expr_or":
                case "expr_logicand":
                case "expr_logicor":
                case "expr_cond":
                    {
                        compiler.compiler_expr.ParseNode_Expr(context, node, out node.Node_Expr _node);
                        context.resultNode = _node;
                    }
                    break;
                case "codedoc":
                case "code_block"://带括号的版本
                    {
                        compiler.compiler_codeblock.ParseNode_CodeBlock(context, node, out node.Node_CodeBlock _node);
                        context.resultNode = _node;
                    }
                    break;
                case "doc"://有上下文影响
                    {
                        if (context.module == null)
                            throw new Exception("must init module before parse doc.");
                        compiler.compiler_doc.ParseNode_Doc_1Pass(context, node);
                    }
                    break;
                default:
                    throw new Exception("can not root from:" + node.type);

            }
        }

        internal static bool Compile2Pass_NameSpace(compiler.CompilerContext ttc, semantic.TTNameSpace _namespace)
        {
            if (!string.IsNullOrEmpty(_namespace.name))
            {
                ttc.PushNameSpace(_namespace);
            }
            if (_namespace.namespaces != null)
                foreach (var n in _namespace.namespaces.Values)
                {
                    if (!Compile2Pass_NameSpace(ttc, n))
                        return false;
                }
            if (_namespace.types != null)
                foreach (var t in _namespace.types.Values)
                {
                    if (!Compile2Pass_Type(ttc, t))
                        return false;
                }
            if (_namespace.methods != null)
                foreach (var m in _namespace.methods.Values)
                {
                    if (!Compile2Pass_Method(ttc, m))
                        return false;
                }
            if (_namespace.vars != null)
                foreach (var v in _namespace.vars.Values)
                {
                    if (!Compile2Pass_Value(ttc, v))
                        return false;
                }
            if (!string.IsNullOrEmpty(_namespace.name))
            {
                ttc.PopNameSpace();
            }
            return true;
        }

        internal static bool Compile2Pass_Type(compiler.CompilerContext ttc, semantic.TTType _type)
        {
            ttc.PushClass(_type);
            if (_type.types != null)
                foreach (var t in _type.types.Values)
                {
                    if (!Compile2Pass_Type(ttc, t))
                        return false;
                }
            if (_type.methods != null)
                foreach (var m in _type.methods.Values)
                {
                    if (!Compile2Pass_Method(ttc, m))
                        return false;
                }
            if (_type.vars != null)
                foreach (var v in _type.vars.Values)
                {
                    if (!Compile2Pass_Value(ttc, v))
                        return false;
                }
            ttc.PopClass();
            return true;
        }
        internal static bool Compile2Pass_Method(compiler.CompilerContext ttc, semantic.TTMethod _method)
        {
            //已经处理好的方法就不保留astnode了
            if (_method.Ready())
                return true;

            foreach (var arg in _method.args)
            {
                Compile2Pass_Arg(ttc, arg);
            }
            ttc.PushMethod(_method);
            if (_method.nobody)
            {
                //不需要body
            }
            else if (_method.notParseNodeBody != null)
            {
                compiler.compiler_codeblock.ParseNode_CodeBlock(ttc, _method.notParseNodeBody, out _method.body);
            }

            if (_method.tttype == null && _method.notParseNodeReturnType != null)
            {
                var b = ttc.FindType(_method.notParseNodeReturnType.text, out _method.ReturnType);
                if (!b)
                    throw new Exception("error return type.");
            }
            else
            {

            }
            ttc.PopMethod();
            return true;
            //return false;
        }
        internal static bool Compile2Pass_Arg(compiler.CompilerContext ttc, semantic.TTArg _value)
        {
            if (_value.notParseType != null)//withtype
            {
                var deftype_name = _value.notParseType.text;
                if (ttc.FindType(deftype_name, out var _type) == false || _type == null)
                {
                    throw new Exception("类型未知");
                }

                _value.argtype = _type;
            }


            if (_value.notParseInitValue != null)
            {//with value
                compiler.compiler_expr.ParseNode_Expr(ttc, _value.notParseInitValue, out node.Node_Expr _node);
                _value.initvalue = _node;
            }
            //强类型语言，expr必须有明确类型，所以直接要就完了
            if (_value.argtype == null && _value.initvalue != null)
            {
                _value.argtype = _value.initvalue.tttype;
            }

            if (_value.argtype == null)
            {
                throw new Exception("不能推出类型");
            }


            return true;
        }
        internal static bool Compile2Pass_Value(compiler.CompilerContext ttc, semantic.TTVar _value)
        {
            if (_value.notParseType != null)//withtype
            {
                var deftype_name = _value.notParseType.text;
                if (ttc.FindType(deftype_name, out var _type) == false || _type == null)
                {
                    throw new Exception("类型未知 in type: " + _value.fullname);
                }

                _value.VarType = _type;
            }


            if (_value.notParseInitValue != null)
            {//with value
                compiler.compiler_expr.ParseNode_Expr(ttc, _value.notParseInitValue, out node.Node_Expr _node);
                _value.initvalue = _node;
            }
            //强类型语言，expr必须有明确类型，所以直接要就完了
            if (_value.tttype == null && _value.initvalue != null)
            {
                _value.VarType = _value.initvalue.tttype;
            }

            if (_value.tttype == null)
            {
                throw new Exception("不能推出类型");
            }


            return true;
        }

    }
}
